package fr.babos.graphic.components.medias 
{
	import com.bit101.components.ListItem;
	import flash.display.Shape;
	import flash.events.ErrorEvent;
	import flash.events.Event;
	import flash.events.LocationChangeEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.media.StageWebView;
	import fr.babos.core.log.Log;
	import fr.babos.graphic.components.base.BaseContainer;
	import fr.babos.graphic.components.base.ResizableComponent;
	import org.osflash.signals.Signal;
	
	/**
	 * Player video natif via un StageWebView.
	 * @author Pascal Achard / ZoulouX
	 */
	public class NativeVideoContainer extends ResizableComponent 
	{
		/**
		 * L'URL de la vidéo
		 */
		protected var _videoURL					:String;
		
		/**
		 * L'URL du poster
		 */
		protected var _posterURL				:String;
		
		/**
		 * Joue automatiquement
		 */
		protected var _autoPlay					:Boolean;
		
		/**
		 * Passe en fullscreen au play
		 */
		protected var _fullscreenOnPlay			:Boolean;
		
		/**
		 * Le StageWebView
		 */
		protected var _stageWebView				:StageWebView;
		
		/**
		 * Le style CSS additionnel
		 */
		protected var _additionalStyle			:String					= "";
		
		/**
		 * Le script Javascript additionnel
		 */
		protected var _additionalScript			:String					= "";
		
		/**
		 * Structure HTML additionnelle
		 */
		protected var _additionalStruct			:String					= "";
		
		/**
		 * Lorsque le player est chargé
		 */
		protected var _onPlayerReady			:Signal					= new Signal();
		
		/**
		 * Afficher / masquer la vidéo
		 */
		override public function get visible ():Boolean { return super.visible; }
		override public function set visible (value:Boolean):void
		{
			super.visible = value;
			
			refreshPosition();
		}
		
		/**
		 * La structure HTML5 du player.
		 */
		protected var _htmlStruct:XML = <root>
			<part1><![CDATA[<!doctype html>
					<html>
						<head>
							<meta charset="utf-8" />
							<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
							<style type="text/css">
								* {
									margin: 0;
									padding: 0;
								}
								html, body {
									position: absolute;
									top: 0;
									right: 0;
									bottom: 0;
									left: 0;
									overflow: hidden;
									background-color: #ccc;
								}
								#media
								{
									width: 100%;
									height: 100%;
								}
								#overlay
								{
									position: absolute;
									top: 0px;
									right: 0px;
									bottom: 0px;
									left:10px;
									background-repeat: no-repeat;
									background-position: center center;
								}
								.ready
								{
									background-image: url('');
								}
								.loading
								{
									background-image: url('');
								}
				]]></part1>
			<part2><![CDATA[
							</style>
							<script type="text/javascript">
								var body;
								var media;
								var overlay;
								var mediaLoaded = false;
								var fullScreenState
								
								function preventMove (event)
								{
									event.preventDefault();
								}
								
								function init ()
								{
									body = document.getElementsByTagName("body")[0];
								}
								
								function loadVid (pUrl, pPoster, pAutoPlay, pGoFullscreen)
								{
									createVideoElement(pUrl, pPoster, pGoFullscreen);
									
									initOverlay();
									
									pauseOnFullScreenChange();
								}
								
								function pauseOnFullScreenChange ()
								{
									fullScreenState = media.webkitDisplayingFullscreen;
									
									window.setInterval(function () {
										if (fullScreenState != media.webkitDisplayingFullscreen && media != null)
										{
											fullScreenState = media.webkitDisplayingFullscreen;
											
											if (!fullScreenState)
											{
												media.pause();
											}
										}
									}, 25);
								}
								
								function createVideoElement (pUrl, pPoster, pGoFullscreen)
								{
									media = document.createElement("video");
									
									media.setAttribute("src", pUrl);
									media.setAttribute("poster", pPoster);
									media.setAttribute("id", "media");
									media.setAttribute("preload", "preload");
									//media.setAttribute("webkit-playsinline", "false");
									//media.setAttribute("webkit-playsfullscreen", "");
									//media.setAttribute("controls", pGoFullscreen ? "" : "controls");
									//media.setAttribute("controls", "controls");
									
									body.appendChild(media);
									
									media.addEventListener("canplay", mediaCanPlay);
									//media.addEventListener("canplaythrough", mediaCanPlay);
									
									if ("load" in media)
										media.load();
									
									//media.play();
									
									//setTimeout(function () {
										//media.pause();
									//}, 1);
								}
								
								function mediaCanPlay ()
								{
									mediaLoaded = true;
									overlay.setAttribute("class", "ready");
								}
								
								function initOverlay ()
								{
									overlay = document.createElement("div");
									
									overlay.setAttribute("id", "overlay");
									overlay.setAttribute("class", "loading");
									
									overlay.addEventListener("touchstart", overlayTapHandler);
									overlay.addEventListener("touchmove", preventMove);
									//overlay.addEventListener("click", overlayTapHandler);
									
									body.appendChild(overlay);
								}
								
								function overlayTapHandler (event)
								{
									event.preventDefault();
									
									if (mediaLoaded)
									{
										media.play();
									}
									
									media.webkitEnterFullscreen();
								}
				]]></part2>
			<part3><![CDATA[
							</script>
						</head>
						<body onload="init()">
				]]></part3>
			<part4><![CDATA[
						</body>
					</html>
				]]></part4>
		</root>;
		
		/**
		 * Le style CSS additionnel
		 */
		public function get additionalStyle ():String { return _additionalStyle; }
		public function set additionalStyle (value:String):void 
		{
			_additionalStyle = value;
		}
		
		/**
		 * Le script Javascript additionnel
		 */
		public function get additionalScript ():String { return _additionalScript; }
		public function set additionalScript (value:String):void 
		{
			_additionalScript = value;
		}
		
		/**
		 * Structure HTML additionnelle
		 */
		public function get additionalStruct ():String { return _additionalStruct; }
		public function set additionalStruct (value:String):void 
		{
			_additionalStruct = value;
		}
		
		/**
		 * Le stageWebView accueuillant la video
		 */
		public function get stageWebView ():StageWebView { return _stageWebView; }
		
		/**
		 * Lorsque le player est chargé
		 */
		public function get onPlayerReady ():Signal { return _onPlayerReady; }
		
		
		/**
		 * Constructeur.
		 */
		public function NativeVideoContainer ()
		{
			
		}
		
		/**
		 * Ajouté au stage.
		 */
		override public function init ():void 
		{
			// On créer le StageWebView
			buildStageWebView();
		}
		
		/**
		 * Créer le stageWebView.
		 */
		protected function buildStageWebView ():void 
		{
			// Créer la vue
			_stageWebView = new StageWebView();
			
			// On écoute
			_stageWebView.addEventListener(Event.COMPLETE, completeHandler);
			_stageWebView.addEventListener(ErrorEvent.ERROR, errorHandler);
			_stageWebView.addEventListener(LocationChangeEvent.LOCATION_CHANGE, locationChangeHandler);
			
			// Le placer
			refreshPosition();
			
			// On le configure
			_stageWebView.stage = stage;
			//_stageWebView.assignFocus();
		}
		
		/**
		 * Joue une vidéo
		 * @param	pURL	L'URL de la vidéo à jouer.
		 */
		public function loadVideo (pVideoURL:String, pPosterURL:String = "", pAutoPlay:Boolean = false, pFullscreenOnPlay:Boolean = false):void 
		{
			// Si le swv n'est pas créer c'est certainement parce que le composant n'est pas sur le stage.
			if (!_stageWebView)
				throw new Error("Attention, le composant doit être placé dans la displayList pour fonctionner.");
			
			// On stock l'URL
			_videoURL = pVideoURL;
			
			// On stock l'URL du poster.
			_posterURL = pPosterURL;
			
			// Autoplay ?
			_autoPlay = pAutoPlay;
			
			// Passe en fullscreen automatiquement ?
			_fullscreenOnPlay = pFullscreenOnPlay;
			
			// On charge le player HTML
			_stageWebView.loadString(compileHTML());
		}
		
		/**
		 * Compiler l'HTML
		 */
		protected function compileHTML ():String
		{
			return _htmlStruct.part1 + _additionalStyle + _htmlStruct.part2 + _additionalScript + _htmlStruct.part3 + _additionalStruct + _htmlStruct.part4;
		}
		
		/**
		 * Appeler une méthode JS sur le stageWebView
		 */
		public function callJavascript (pFunctionName:String, pParams:Array):void
		{
			var functionCall:String = "javascript:" + pFunctionName + "(";
			
			const total:uint = pParams.length;
			for (var i:uint = 0; i < total; i++)
			{
				if (typeof(pParams[i]) == "string")
					functionCall += '"' + pParams[i] + '"';
				else
					functionCall += pParams[i];
				
				if (i != total -1)
					functionCall += ", ";
			}
			
			functionCall += ")";
			
			// On change les propriétés du player HTML5
			_stageWebView.loadURL(functionCall);
		}
		
		/**
		 * Besoin de rafraichir la position
		 */
		override protected function needReplace (pNeedResized:Boolean = false):void 
		{
			// Relayer
			super.needReplace(pNeedResized);
			
			// Réappliquer au stageWebView
			refreshPosition();
		}
		
		/**
		 * Actualiser les positions / dimensions du stageWebView
		 */
		public function refreshPosition ():void 
		{
			// Si on a un stageWebView
			if (_stageWebView != null)
			{
				if (super.visible)
				{
					// Récupérer le point de référence de la position de notre clip
					var registerPoint:Point = new Point();
					registerPoint = localToGlobal(registerPoint);
					
					// On lui applique un viewPort
					_stageWebView.viewPort = new Rectangle(
						registerPoint.x,
						registerPoint.y,
						_localWidth,
						_localHeight
					);
				}
				else
				{
					_stageWebView.viewPort = new Rectangle(- _localWidth - 1, - _localHeight - 1, _localWidth, _localHeight);
				}
			}
		}
		
		/**
		 * Le chargement du StageWebView est terminé.
		 */
		protected function completeHandler (event:Event):void 
		{
			callJavascript("loadVid", [
				_videoURL,
				_posterURL,
				_autoPlay,
				_fullscreenOnPlay
			]);
			
			_onPlayerReady.dispatch();
		}
		
		/**
		 * Le Location du StageWebView change
		 */
		protected function locationChangeHandler (event:LocationChangeEvent):void 
		{
			Log.notice("NativeVideoContainer.locationChangeHandler", event);
		}
		
		/**
		 * Il y a une erreur dans le StageWebView
		 */
		protected function errorHandler (event:ErrorEvent):void 
		{
			Log.error("NativeVideoContainer.locationChangeHandler" + event.toString());
		}
		
		/**
		 * Nettoie ta chambre !
		 */
		override public function dispose ():void
		{
			// Relayer
			super.dispose();
			
			// Si on a un stageWebView
			if (_stageWebView != null)
			{
				// On vire l'écoute
				_stageWebView.removeEventListener(Event.COMPLETE, completeHandler);
				_stageWebView.removeEventListener(ErrorEvent.ERROR, errorHandler);
				_stageWebView.removeEventListener(LocationChangeEvent.LOCATION_CHANGE, locationChangeHandler);
				
				// On le supprime
				_stageWebView.viewPort = null;
				_stageWebView.stage = null;
				_stageWebView.dispose();
				_stageWebView = null;
			}			
		}
	}
}